package com.pzl.util;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RectShape;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.StatFs;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.view.View;

import com.orhanobut.logger.Logger;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;


public class BitmapUtil {

    private static final String TAG = "BitmapUtil";

    /**
     * A default size to use to increase hit rates when the required size isn't defined.
     * Currently 64KB.
     */
    public final static int DEFAULT_BUFFER_SIZE = 64 * 1024;

    /**
     * 读取本地资源的图片
     *
     * @param context
     * @param resId
     * @return
     */
    public static Bitmap readBitmapByResId(Context context, int resId) {
        BitmapFactory.Options opt = new BitmapFactory.Options();
        opt.inPreferredConfig = Config.RGB_565;
        opt.inPurgeable = true;
        opt.inInputShareable = true;
        // 获取资源图片
        InputStream is = context.getResources().openRawResource(resId);
        return BitmapFactory.decodeStream(is, null, opt);
    }

    /**
     * 根据资源文件获取Bitmap
     *
     * @param context
     * @param drawableId
     * @return
     */
    public static Bitmap readBitmapByResId(Context context, int drawableId,
                                           int screenWidth, int screenHight) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Config.ARGB_8888;
        options.inInputShareable = true;
        options.inPurgeable = true;
        InputStream stream = context.getResources().openRawResource(drawableId);
        Bitmap bitmap = BitmapFactory.decodeStream(stream, null, options);
        return getBitmap(bitmap, screenWidth, screenHight);
    }

    /**
     * 根据sdcard文件获取Bitmap
     *
     * @param file
     * @param screenWidth
     * @param screenHight
     * @return
     */
    public static Bitmap readBitmapByPath(File file, int screenWidth, int screenHight) {
        if (!file.exists()) {
            Logger.d("readBitmapByPath.file = " + file);
            return null;
        }
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Config.ARGB_8888;
        options.inInputShareable = true;
        options.inPurgeable = true;
        BufferedInputStream stream = getStreamFile(file);
        if (stream != null) {
            Bitmap bitmap = BitmapFactory.decodeStream(stream);
            return getBitmap(bitmap, screenWidth, screenHight);
        } else {
            return null;
        }
    }

    /**
     * 根据sdcard文件获取Bitmap
     *
     * @param file
     * @return
     */
    public static Bitmap readBitmapByPath(File file) {
        if (!file.exists())
            return null;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Config.ARGB_4444;
        options.inInputShareable = true;
        options.inPurgeable = true;
        BufferedInputStream stream = getStreamFile(file);
        if (stream != null) {
            Bitmap bitmap = BitmapFactory.decodeStream(stream);
            return bitmap;
        } else {
            return null;
        }
    }

    /**
     * 根据sdcard文件获取Bitmap
     *
     * @param filePath
     * @return
     */
    public static Bitmap readBitmapByPath(String filePath) {
        File file = new File(filePath);
        if (!file.exists())
            return null;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Config.ARGB_4444;
        options.inInputShareable = true;
        options.inPurgeable = true;
        BufferedInputStream stream = getStreamFile(file);
        if (stream != null) {
            Bitmap bitmap = BitmapFactory.decodeStream(stream);
            return bitmap;
        } else {
            return null;
        }
    }

    /**
     * 将图片按照固定大小取缩略图，并保证图片不失真。
     *
     * @param imagePath 图片所存路径
     * @return bitmap
     */
    public static Bitmap compressPicture(final String imagePath) {
        // 将图片按照固定大小取缩略图，并保证图片不失真。
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        Bitmap bitmap = BitmapFactory.decodeFile(imagePath, options); // 此时返回bm为空
        options.inJustDecodeBounds = false;
        // 缩放比
        int tempH = (int) (options.outHeight / (float) 150);
        if (tempH <= 0)
            tempH = 1;
        options.outHeight = tempH;
        int tempW = (int) (options.outWidth / (float) 196);
        if (tempW <= 0)
            tempW = 1;
        options.outWidth = tempW;
        // 重新读入图片，注意这次要把options.inJustDecodeBounds 设为 false哦
        bitmap = BitmapFactory.decodeFile(imagePath, options);
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
        return bitmap;
    }

    /**
     * 将图片按照固定大小取缩略图。
     *
     * @param imagePath 图片所存路径
     * @return bitmap
     */
    public static Bitmap compressPictureXYAndTime(final String imagePath, int oldWidth, int oldHeight) {
        // 将图片按照固定大小取缩略图，并保证图片不失真。
        BitmapFactory.Options opts = new BitmapFactory.Options();
        // opts.inSampleSize = 4;
        opts.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(imagePath, opts);
        opts.inSampleSize = computeSampleSize(opts, -1, oldWidth * oldHeight);
        opts.inJustDecodeBounds = false;

        Bitmap bitmap = null;
        try {
            bitmap = BitmapFactory.decodeFile(imagePath, opts); // 此时返回bm为空
            // 获取这个图片的宽和高
            int width = bitmap.getWidth();
            int height = bitmap.getHeight();
            // 定义预转换成的图片的宽度和高度
            int newWidth = oldWidth;
            int newHeight = oldHeight;
            // 计算缩放率，新尺寸除原始尺寸
            float scaleWidth = ((float) newWidth) / width;
            float scaleHeight = ((float) newHeight) / height;
            // 创建操作图片用的matrix对象
            Matrix matrix = new Matrix();
            // 缩放图片动作
            matrix.postScale(scaleWidth, scaleHeight);
            // 旋转图片 动作
            matrix.postRotate(0);
            // 创建新的图片
            Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);

            // 在图片右下角画出当前时间
            drawText(resizedBitmap);

            int w = resizedBitmap.getWidth();
            int h = resizedBitmap.getHeight();
            bitmap.recycle();
            return resizedBitmap;
        } catch (Exception e) {
            return null;
        }
    }

    public static boolean drawText(String imagePath, int width, int height) {
        try {
            Bitmap bitmap = getLocalPicture(imagePath, width, height);
            Canvas canvasTemp = new Canvas(bitmap);
            Paint p = new Paint();
            Typeface font = Typeface.create("宋体", Typeface.BOLD);
            p.setColor(Color.RED);
            p.setTypeface(font);
            p.setTextSize(18);
            canvasTemp.drawText(DateUtil.formatDateOfSecond(), bitmap.getWidth() - 220, bitmap.getHeight() - 20, p);
            canvasTemp.save(Canvas.ALL_SAVE_FLAG);// 保存
            canvasTemp.restore();// 存储
            // 重新保存绘画后的图片
            saveDrawPictrue(imagePath, bitmap, 50);
        } catch (Exception e) {
            Logger.e(e.getMessage(), e);
            return false;
        }
        return true;
    }

    public static void saveDrawPictrue(String imagePath, Bitmap bitmap, int quality) {
        File file = new File(imagePath);
        if (!file.exists()) {
            file.mkdirs();
        }
        try {
            FileOutputStream fos = new FileOutputStream(file);
            bitmap.compress(Bitmap.CompressFormat.JPEG, quality, fos); // 压缩50%质量比例
            fos.close();
        } catch (Exception e) {
            Logger.e(e.getMessage(), e);
        }
    }

    public static void drawText(Bitmap resizedBitmap) {
        Canvas canvasTemp = new Canvas(resizedBitmap);
        Paint p = new Paint();
        Typeface font = Typeface.create("宋体", Typeface.BOLD);
        p.setColor(Color.RED);
        p.setTypeface(font);
        p.setTextSize(18);
        canvasTemp.drawText(DateUtil.formatDateOfSecond(),
                resizedBitmap.getWidth() - 220, resizedBitmap.getHeight() - 20,
                p);
        canvasTemp.save(Canvas.ALL_SAVE_FLAG);// 保存
        canvasTemp.restore();// 存储
    }

    /**
     * 按质量压缩图片的方法
     *
     * @param image
     * @return
     */
    public static Bitmap compressImage(Bitmap image) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
        int options = 90;
        while (baos.toByteArray().length / 1024 > 100) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
            baos.reset();// 重置baos即清空baos
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%，把压缩后的数据存放到baos中
            options -= 10;// 每次都减少10
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片
        return bitmap;
    }

    /**
     * 将图片按照固定大小取缩略图。
     *
     * @param imagePath 图片所存路径
     * @return bitmap
     */
    public static Bitmap compressPictureXYSmall(String imagePath, int imgWidth, int imgheight) {
        // 将图片按照固定大小取缩略图，并保证图片不失真。
        BitmapFactory.Options opts = new BitmapFactory.Options();
        // opts.inSampleSize = 4;
        opts.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(imagePath, opts);
        opts.inSampleSize = computeSampleSize(opts, -1, imgWidth * imgheight);
        opts.inJustDecodeBounds = false;
        Bitmap bitmap = null;
        try {
            bitmap = BitmapFactory.decodeFile(imagePath, opts); // 此时返回bm为空
            // 获取这个图片的宽和高
            int width = bitmap.getWidth();
            int height = bitmap.getHeight();
            // 定义预转换成的图片的宽度和高度
            int newWidth = imgWidth;
            int newHeight = imgheight;
            // 计算缩放率，新尺寸除原始尺寸
            float scaleWidth = ((float) newWidth) / width;
            float scaleHeight = ((float) newHeight) / height;
            // 创建操作图片用的matrix对象
            Matrix matrix = new Matrix();
            // 缩放图片动作
            matrix.postScale(scaleWidth, scaleHeight);
            // 旋转图片 动作
            matrix.postRotate(0);
            // 创建新的图片
            Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
            bitmap.recycle();
            return resizedBitmap;
        } catch (Exception e) {
            return null;
        }
    }

    public static void extractThumbnail(String imagePath, int imgWidth, int imgheight) {
        try {
            Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
            if (null == bitmap) return;
            int bitmapWidth = bitmap.getWidth();
            int bitmapHeight = bitmap.getHeight();
            if (bitmapWidth <= 720 && bitmapWidth < bitmapHeight) {
                if (!bitmap.isRecycled()) {
                    bitmap.recycle();//记得释放资源，否则会内存溢出
                }
                return;
            }
            // 缩放图片的尺寸
            float scaleWidth;
            float scaleHeight;
            if (bitmapWidth < bitmapHeight) {
                scaleWidth = (float) imgheight / bitmapWidth;
                scaleHeight = (float) imgWidth / bitmapHeight;
            } else {
                scaleWidth = (float) imgWidth / bitmapWidth;
                scaleHeight = (float) imgheight / bitmapHeight;
            }
            Matrix matrix = new Matrix();
            matrix.postScale(scaleWidth, scaleHeight);
            // 产生缩放后的Bitmap对象
            Bitmap resizeBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmapWidth, bitmapHeight, matrix, false);
            // save file
            File myCaptureFile = new File(imagePath);
            FileOutputStream out = new FileOutputStream(myCaptureFile);
            // 保存图片格式
            String imageFormat = imagePath.substring(imagePath.lastIndexOf("."));
            if (imageFormat.equals(".jpg") || imageFormat.equals(".JPG")) {
                if (resizeBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out)) {
                    out.flush();
                    out.close();
                }
            } else if (imageFormat.equals(".png") || imageFormat.equals(".PNG")) {
                if (resizeBitmap.compress(Bitmap.CompressFormat.PNG, 100, out)) {
                    out.flush();
                    out.close();
                }
            }

            if (!bitmap.isRecycled()) {
                bitmap.recycle();//记得释放资源，否则会内存溢出
            }
            if (!resizeBitmap.isRecycled()) {
                resizeBitmap.recycle();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    /**
     * 将图片按照固定大小取缩略图。
     *
     * @param imagePath 图片所存路径
     * @return bitmap
     */
    public static Bitmap compressPicture(String imagePath, int imgWidth, int imgheight) {
        // 将图片按照固定大小取缩略图，并保证图片不失真。
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(imagePath, opts);
        opts.inSampleSize = computeSampleSize(opts, -1, imgWidth * imgheight);
        opts.inJustDecodeBounds = false;

        Bitmap bitmap = null;
        InputStream is = null;
        try {
            is = new FileInputStream(new File(imagePath));
            bitmap = BitmapFactory.decodeStream(is, null, opts); // 此时返回bm为空
            // 获取这个图片的宽和高
            int width = bitmap.getWidth();
            int height = bitmap.getHeight();
            // 定义预转换成的图片的宽度和高度
            int newWidth = imgWidth;
            int newHeight = imgheight;
            // 计算缩放率，新尺寸除原始尺寸
            float scaleWidth = ((float) newWidth) / width;
            float scaleHeight = ((float) newHeight) / height;
            // 创建操作图片用的matrix对象
            Matrix matrix = new Matrix();
            // 缩放图片动作
            matrix.postScale(scaleWidth, scaleHeight);
            // 旋转图片 动作
            matrix.postRotate(0);
            // 创建新的图片
            Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
            return resizedBitmap;
        } catch (Exception e) {
            return null;
        } catch (OutOfMemoryError e) {
            return null;
        } finally {
            if (bitmap != null) {
                bitmap.recycle();
            }
            try {
                is.close();
            } catch (IOException e) {
                Logger.e(e.getMessage(), e);
            }
        }
    }

    /**
     * 动态计算BitmapFactory分配更少的空间
     *
     * @param options
     * @param minSideLength
     * @param maxNumOfPixels
     * @return
     */
    public static int computeSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) {
        int initialSize = computeInitialSampleSize(options, minSideLength, maxNumOfPixels);
        int roundedSize;
        if (initialSize <= 8) {
            roundedSize = 1;
            while (roundedSize < initialSize) {
                roundedSize <<= 1;
            }
        } else {
            roundedSize = (initialSize + 7) / 8 * 8;
        }
        return roundedSize;
    }

    /**
     * 动态计算像素大小
     *
     * @param options
     * @param minSideLength
     * @param maxNumOfPixels
     * @return
     */
    private static int computeInitialSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) {
        double w = options.outWidth;
        double h = options.outHeight;
        int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
        int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(Math.floor(w / minSideLength), Math.floor(h / minSideLength));
        if (upperBound < lowerBound) {
            // return the larger one when there is no overlapping zone.
            return lowerBound;
        }

        if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
            return 1;
        } else if (minSideLength == -1) {
            return lowerBound;
        } else {
            return upperBound;
        }
    }


    /**
     * 获取本地图片，并将图片按照固定大小取缩略图。
     *
     * @param imagePath 图片所存路径
     * @param width
     * @param height
     * @return bitmap
     */
    public static Bitmap getLocalPicture(String imagePath, int width, int height) {
        try {
            // 将图片按照固定大小取缩略图，并保证图片不失真。
            BitmapFactory.Options opts = new BitmapFactory.Options();
            // opts.inSampleSize = 4;
            opts.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(imagePath, opts);
            opts.inSampleSize = computeSampleSize(opts, -1, width * height);
            opts.inJustDecodeBounds = false;

            Bitmap bitmap = BitmapFactory.decodeFile(imagePath, opts);
            return bitmap.copy(Bitmap.Config.ARGB_8888, true);
        } catch (Exception e) {
            return null;
        }
    }


    private static Bitmap decodeBitmap(InputStream is) {
        if (is == null) {
            return null;
        }
        BitmapFactory.Options options = new BitmapFactory.Options();
        // 设置该属性可以不占用内存，并且能够得到bitmap的宽高等属性，此时得到的bitmap是空
        options.inJustDecodeBounds = true;
        byte[] data = inputStream2ByteArray(is);// 将InputStream转为byte数组，可以多次读取
        Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length,
                options);
        // 设置计算得到的压缩比例
        options.inSampleSize = 4;
        // 设置为false，确保可以得到bitmap != null
        options.inJustDecodeBounds = false;
        bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);
        return bitmap;
    }

    public static byte[] inputStream2ByteArray(InputStream inputStream) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        byte[] buff = new byte[1024];
        int len = 0;
        try {
            while ((len = inputStream.read(buff)) != -1) {
                outputStream.write(buff, 0, len);
            }
            inputStream.close();
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace(); // To change body of catch statement use File |
            // Settings | File Templates.
        }
        return outputStream.toByteArray();
    }


    public static BufferedInputStream getStreamFile(File file) {
        if (!file.exists())
            return null;
        try {
            BufferedInputStream stream = new BufferedInputStream(new FileInputStream(file));
            return stream;
        } catch (FileNotFoundException e) {
            Logger.e(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 等比例压缩图片
     *
     * @param bitmap
     * @param screenWidth
     * @param screenHight
     * @return
     */
    public static Bitmap getBitmap(Bitmap bitmap, int screenWidth, int screenHight) {
        if (null == bitmap) return null;
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
        Matrix matrix = new Matrix();
        float scale = (float) screenWidth / w;
        float scale2 = (float) screenHight / h;

        // 保证图片不变形.
        matrix.postScale(scale, scale2);
        // w,h是原图的属性.
        return Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
    }

    /**
     * 保存图片至SD卡
     *
     * @param bm
     * @param url
     * @param quantity
     */
    private static int FREE_SD_SPACE_NEEDED_TO_CACHE = 1;
    private static int MB = 1024 * 1024;
    public static String DIR = null;

    public static void saveBmpToSd(Bitmap bm, String url, int quantity) {
        // 判断sdcard上的空间
        if (FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
            return;
        }
        if (!Environment.MEDIA_MOUNTED.equals(Environment
                .getExternalStorageState()))
            return;
        String filename = url;
        DIR = FileUtil.createSDCardFolder(FileUtil.SDCARD_CACHE_IMAGE_DIR + File.separator + DateUtil.fileDayName());
        // 目录不存在就创建
        File dirPath = new File(DIR);
        if (!dirPath.exists()) {
            dirPath.mkdirs();
        }

        File file = new File(DIR + "/" + filename);
        try {
            file.createNewFile();
            OutputStream outStream = new FileOutputStream(file);
            bm.compress(Bitmap.CompressFormat.PNG, quantity, outStream);
            outStream.flush();
            outStream.close();

        } catch (FileNotFoundException e) {

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 获取SD卡图片
     *
     * @param url
     * @param quantity
     * @return
     */
    public static Bitmap getBitmap(String url, int quantity) {
        InputStream inputStream = null;
        String filename = "";
        Bitmap map = null;
        URL url_Image = null;
        String LOCALURL = "";
        if (url == null)
            return null;
        try {
            filename = url;
        } catch (Exception err) {
        }

        DIR = FileUtil.createSDCardFolder(FileUtil.SDCARD_CACHE_IMAGE_DIR);

        LOCALURL = URLEncoder.encode(filename);
        if (exist(DIR + "/" + LOCALURL)) {
            map = BitmapFactory.decodeFile(DIR + "/" + LOCALURL);
        } else {
            try {
                url_Image = new URL(url);
                inputStream = url_Image.openStream();
                map = BitmapFactory.decodeStream(inputStream);
                // url = URLEncoder.encode(url, "UTF-8");
                if (map != null) {
                    saveBmpToSd(map, LOCALURL, quantity);
                }
                inputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
        return map;
    }

    /**
     * 判断图片是存在
     *
     * @param url
     * @return
     */
    public static boolean exist(String url) {
        DIR = FileUtil.createSDCardFolder(FileUtil.SDCARD_CACHE_IMAGE_DIR);
        File file = new File(DIR + url);
        return file.exists();
    }

    /**
     * 计算sdcard上的剩余空间 * @return
     */
    private static int freeSpaceOnSd() {
        StatFs stat = new StatFs(Environment.getExternalStorageDirectory()
                .getPath());
        double sdFreeMB = ((double) stat.getAvailableBlocks() * (double) stat
                .getBlockSize()) / MB;

        return (int) sdFreeMB;
    }

    /**
     * 从view 得到图片
     *
     * @param view
     * @return
     */
    public static Bitmap getBitmapFromView(View view) {
        view.destroyDrawingCache();
        view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
        view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
        view.setDrawingCacheEnabled(true);
        Bitmap bitmap = view.getDrawingCache(true);
        return bitmap;
    }


    /**
     * 绘制背景图片和展示图片
     *
     * @param smallBgBitmap
     * @param localBitmap
     * @return
     */
    public static Drawable getDrawable(Bitmap smallBgBitmap, Bitmap localBitmap) {
        ShapeDrawable sd = new ShapeDrawable(new RectShape());
        Paint p = sd.getPaint();
        Bitmap normalBitmap = Bitmap.createBitmap(smallBgBitmap.getWidth(), smallBgBitmap.getHeight(), Config.ARGB_8888);
        Canvas canvas = new Canvas(normalBitmap);
        /* 将smallBgBitmap、localBitmap绘制到normalBitmap上 */
        canvas.drawBitmap(smallBgBitmap, 0, 0, p);
        canvas.drawBitmap(localBitmap, (smallBgBitmap.getWidth() - localBitmap.getWidth()) / 2, (smallBgBitmap.getHeight() - localBitmap.getHeight()) / 2, p);
        return new BitmapDrawable(normalBitmap);
    }

    /**
     * 单纯绘制图片
     *
     * @param bitmap
     * @param width
     * @param height
     * @return
     */
    public static Drawable getDrawable(Bitmap bitmap, int width, int height) {
        ShapeDrawable sd = new ShapeDrawable(new RectShape());
        Paint p = sd.getPaint();
        Bitmap normalBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
        Canvas canvas = new Canvas(normalBitmap);
        /* 将bitmap绘制到normalBitmap上 */
        canvas.drawBitmap(bitmap, 0, 0, p);
        return new BitmapDrawable(normalBitmap);
    }

    /**
     * 绘制图片和字符串
     *
     * @param bitmap
     * @param width
     * @param height
     * @param text
     * @return
     */
    public static Drawable getDrawable(Bitmap bitmap, int width, int height, String text) {
        ShapeDrawable sd = new ShapeDrawable(new RectShape());
        Paint p = sd.getPaint();
        //create cache erea
        Bitmap normalBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
        Canvas canvas = new Canvas(normalBitmap);
        /* 将bitmap绘制到normalBitmap上 */
        canvas.drawBitmap(bitmap, 0, 0, p);
        p.setARGB(255, 255, 255, 255);
        if (text.length() > 5) {
            p.setTextSize(12);
        } else {
            p.setTextSize(16);
        }
        Logger.d("text = " + text);
        String[] texts = text.split(" ");
        if (texts.length > 1) {
            int h = 15;
            int h2 = 13;
            if (texts.length == 2) {
                for (int i = 0; i < texts.length; i++) {
                    //字体居中
                    Rect bounds = new Rect();
                    p.getTextBounds(texts[i], 0, texts[i].length(), bounds);
                    canvas.drawText(texts[i], (bitmap.getWidth() - bounds.width()) / 2, (bitmap.getHeight() + bounds.height()) / 2 + (i - 1) * h, p);
                }
            } else if (texts.length == 3) {
                for (int i = 0; i < texts.length; i++) {
                    //字体居中
                    Rect bounds = new Rect();
                    p.getTextBounds(texts[i], 0, texts[i].length(), bounds);
                    canvas.drawText(texts[i], (bitmap.getWidth() - bounds.width()) / 2, (bitmap.getHeight() + bounds.height()) / 2 + (i - 1) * (i == 2 ? h2 : h), p);
                }
            }
        } else {
            Rect bounds = new Rect();
            p.getTextBounds(text, 0, text.length(), bounds);
            canvas.drawText(text, (bitmap.getWidth() - bounds.width()) / 2, (bitmap.getHeight() + bounds.height()) / 2, p);
        }
        return new BitmapDrawable(normalBitmap);
    }

    public static int max = 0;
    public static boolean act_bool = true;
    public static List<Bitmap> bmp = new ArrayList<Bitmap>();
    public static List<String> drr = new ArrayList<String>();

    public static Bitmap revitionImageSize(String path) throws IOException {
        BufferedInputStream in = new BufferedInputStream(new FileInputStream(
                new File(path)));
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(in, null, options);
        in.close();
        int i = 0;
        Bitmap bitmap = null;
        while (true) {
            if ((options.outWidth >> i <= 1000)
                    && (options.outHeight >> i <= 1000)) {
                in = new BufferedInputStream(
                        new FileInputStream(new File(path)));
                options.inSampleSize = (int) Math.pow(2.0D, i);
                options.inJustDecodeBounds = false;
                bitmap = BitmapFactory.decodeStream(in, null, options);
                break;
            }
            i += 1;
        }
        return bitmap;
    }


    public static Bitmap bytes2Bimap(byte[] b) {
        if (b.length != 0) {
            return BitmapFactory.decodeByteArray(b, 0, b.length);
        } else {
            return null;
        }
    }

    /*
    * 旋转图片
    * @param angle
    * @param bitmap
    * @return Bitmap
    */
    public static Bitmap rotaingImageView(int angle, Bitmap bitmap) {
        //旋转图片 动作
        Matrix matrix = new Matrix();
        ;
        matrix.postRotate(angle);
        // 创建新的图片
        Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        return resizedBitmap;
    }

    /**
     * To byte array byte [ ].
     *
     * @param bitmap the bitmap
     * @return the byte [ ]
     */
    public static byte[] toByteArray(Bitmap bitmap) {
        if (bitmap == null) {
            return null;
        }
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        // 将Bitmap压缩成PNG编码，质量为100%存储，除了PNG还有很多常见格式，如jpeg等。
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, os);
        byte[] bytes = os.toByteArray();
        try {
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bytes;
    }

    /**
     * To bitmap bitmap.
     *
     * @param bytes  the bytes
     * @param width  the width
     * @param height the height
     * @return the bitmap
     */
    public static Bitmap toBitmap(byte[] bytes, int width, int height) {
        Bitmap bitmap = null;
        if (bytes.length != 0) {
            try {
                BitmapFactory.Options options = new BitmapFactory.Options();
                // 不进行图片抖动处理
                options.inDither = false;
                // 设置让解码器以最佳方式解码
                options.inPreferredConfig = null;
                if (width > 0 && height > 0) {
                    options.outWidth = width;
                    options.outHeight = height;
                }
                bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
            } catch (Exception e) {
            }
        }
        return bitmap;
    }

    /**
     * To bitmap bitmap.
     *
     * @param bytes the bytes
     * @return the bitmap
     */
    public static Bitmap toBitmap(byte[] bytes) {
        return toBitmap(bytes, -1, -1);
    }

    /**
     * convert Drawable to Bitmap
     * 参考：http://kylines.iteye.com/blog/1660184
     *
     * @param drawable the drawable
     * @return bitmap bitmap
     */
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public static Bitmap toBitmap(Drawable drawable) {
        if (drawable instanceof BitmapDrawable) {
            return ((BitmapDrawable) drawable).getBitmap();
        } else if (drawable instanceof ColorDrawable) {
            //color
            Bitmap bitmap = Bitmap.createBitmap(32, 32, Bitmap.Config.ARGB_8888);
            if (Build.VERSION.SDK_INT >= 11) {
                Canvas canvas = new Canvas(bitmap);
                canvas.drawColor(((ColorDrawable) drawable).getColor());
            }
            return bitmap;
        } else if (drawable instanceof NinePatchDrawable) {
            //.9.png
            Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
                    drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(bitmap);
            drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
            drawable.draw(canvas);
            return bitmap;
        }
        return null;
    }

    /**
     * convert Bitmap to Drawable
     *
     * @param bitmap the bitmap
     * @return drawable drawable
     */
    public static Drawable toDrawable(Bitmap bitmap) {
        return bitmap == null ? null : new BitmapDrawable(null, bitmap);
    }

    /**
     * convert Drawable to byte array
     *
     * @param drawable the drawable
     * @return byte [ ]
     */
    public static byte[] toByteArray(Drawable drawable) {
        return toByteArray(toBitmap(drawable));
    }

    /**
     * convert byte array to Drawable
     *
     * @param bytes the bytes
     * @return drawable drawable
     */
    public static Drawable toDrawable(byte[] bytes) {
        return toDrawable(toBitmap(bytes));
    }

    public static Bitmap compress(String imagePath, int maxWidth, int maxHeight) {

        if (TextUtils.isEmpty(imagePath)) {
            return null;
        }

        File rawFile = new File(imagePath);
        if (!rawFile.exists()) {
            return null;
        }

        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(imagePath, opts);
        opts.inSampleSize = caculateInSampleSize(opts.outWidth, opts.outHeight, maxWidth, maxHeight);
        opts.inJustDecodeBounds = false;

        return BitmapFactory.decodeFile(imagePath, opts);
    }

    public static Bitmap compress(Bitmap sourceBitmap, int maxBytes, FileType fileType) {

        if (fileType == FileType.JPEG) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            sourceBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
            int quality = 90;
            while (baos.toByteArray().length > maxBytes) {

                baos.reset();
                sourceBitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);

                if (quality > 50) {
                    quality -= 10;
                } else if (quality > 30) {
                    quality -= 5;
                } else {
                    break;
                }
            }
            ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
            return BitmapFactory.decodeStream(isBm, null, null);
        } else if (fileType == FileType.PNG) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            sourceBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
            int quality = 90;
            while (baos.toByteArray().length > maxBytes) {

                baos.reset();
                sourceBitmap.compress(Bitmap.CompressFormat.PNG, quality, baos);

                if (quality > 50) {
                    quality -= 10;
                } else if (quality > 30) {
                    quality -= 5;
                } else {
                    break;
                }
            }
            ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
            return BitmapFactory.decodeStream(isBm, null, null);
        } else {

            return sourceBitmap;
        }
    }

    public static void compress(Bitmap sourceBitmap, int maxBytes, FileType fileType, String savePath) {

        try {
            Bitmap bitmap = compress(sourceBitmap, maxBytes, fileType);

            FileOutputStream fos = new FileOutputStream(new File(savePath));

            if (fileType == FileType.PNG) {
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
            } else if (fileType == FileType.JPEG) {
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            } else {

                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            }
            fos.flush();
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param maxWidth
     * @param maxHeight
     * @return
     */
    private static int caculateInSampleSize(int rawWidth, int rawHeight, int maxWidth, int maxHeight) {

        if (rawWidth <= 0 || rawHeight <= 0) {
            throw new IllegalArgumentException();
        }

        int inSamleSize = 1;
        if (maxWidth <= 0 && maxHeight <= 0) {
            inSamleSize = 1;
        } else {

            if (maxWidth <= 0 && maxHeight < rawHeight) {

                inSamleSize = rawHeight / maxHeight;
            }

            if (maxHeight <= 0 && maxWidth < rawWidth) {

                inSamleSize = rawWidth / maxWidth;
            }

            if (maxWidth > 0 && maxHeight > 0 && (maxWidth < rawWidth || maxHeight < rawHeight)) {

                float widthRatio = (float) rawWidth / maxWidth;
                float heightRatio = (float) rawHeight / maxHeight;

                if (widthRatio > heightRatio) {

                    inSamleSize = rawWidth / maxWidth;
                } else {

                    inSamleSize = rawHeight / maxHeight;
                }
            }
        }
        return inSamleSize;
    }

    /**
     * @param path
     * @return
     */
    public static int readPictureDegree(String path) {
        int degree = 0;
        try {
            ExifInterface exifInterface = new ExifInterface(path);
            int orientation = exifInterface.getAttributeInt(
                    ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return degree;
    }

    /**
     * 设置图片大小
     *
     * @param bm        ：原图
     * @param newWidth  ：最终希望得到的宽
     * @param newHeight ：最终希望得到的高
     */
    public static Bitmap resizeBitmap(Bitmap bm, int newWidth, int newHeight) {
        int width = bm.getWidth();
        int height = bm.getHeight();
        // 计算缩放比例
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        // 取得想要缩放的matrix参数
        Matrix matrix = new Matrix();
        float scale = (scaleWidth <= scaleHeight) ? scaleWidth : scaleHeight;
        matrix.postScale(scale, scale);
        // 设置大小
        return Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
    }

    /**
     * 带旋转的，缩放图片，会按照 宽高缩放比 较小的值进行缩放
     *
     * @param bm
     * @param newWidth
     * @param newHeight
     * @param rotate    旋转参数
     * @return
     */
    public static Bitmap resizeBitmap(Bitmap bm, int newWidth, int newHeight,
                                      int rotate) {
        int width = bm.getWidth();
        int height = bm.getHeight();
        // 计算缩放比例
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        // 取得想要缩放的matrix参数
        Matrix matrix = new Matrix();
        float scale = (scaleWidth <= scaleHeight) ? scaleWidth : scaleHeight;
        matrix.postScale(scale, scale);
        matrix.postRotate(rotate);
        // 设置大小
        return Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
    }

    /**
     * 获取旋转参数
     *
     * @param imagePath
     * @return
     */
    public static int getCameraPhotoOrientation(String imagePath) {
        int rotate = 0;
        try {
            File imageFile = new File(imagePath);
            ExifInterface exif = new ExifInterface(imageFile.getAbsolutePath());
            int orientation = exif.getAttributeInt(
                    ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);

            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_270:
                    rotate = 270;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    rotate = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_90:
                    rotate = 90;
                    break;
            }

            // Log.v(TAG, "Exif orientation: " + orientation);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return rotate;
    }

    /**
     * 将图片按照宽高中比较小的裁剪成正方形
     *
     * @param bm
     * @return
     */
    public static Bitmap cropBitmap(Bitmap bm) {
        int height = bm.getHeight();
        int width = bm.getWidth();
        if (height > width) {
            return Bitmap.createBitmap(bm, 0, (height - width) / 4, width,
                    width);
        } else {
            return Bitmap.createBitmap(bm, (width - height) / 2, 0, height,
                    height);
        }
    }


    /**
     * 将指定路径的图片根据指定宽度缩放(支持大图片)
     *
     * @param filePath
     * @param width
     * @return
     */
    public static Bitmap getMicroImage(String filePath, int width) {
        // 获取文件输入流
        InputStream is = null;
        Bitmap bitmap = null;
        try {
            File f = new File(filePath);
            is = new FileInputStream(f);
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            // 获取调整后的options
            BitmapFactory.decodeFile(filePath, options);
            int height = options.outHeight * width / options.outWidth;
            if (is != null) {
                int isSize = is.available();
                // 大于1M=1048576字节，则视为大图
                int base = 309600;
                if (isSize > base) {
                    options.inSampleSize = 10; // width，hight设为原来的十分一
                } else if (isSize <= 409600 && isSize > 104800) {
                    options.inSampleSize = 4;
                } else if (isSize <= 104800 && isSize > 60) {
                    options.inSampleSize = 2;
                } else {
                    options.inSampleSize = 1;
                }
            }
            options.inJustDecodeBounds = false;
            bitmap = BitmapFactory.decodeStream(is, null, options);
            int rotate = getCameraPhotoOrientation(filePath);
            bitmap = resizeBitmap(bitmap, width, height,
                    rotate);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return bitmap;
    }

    /**
     * 根据路径，不失真压缩
     *
     * @param filePath
     * @return
     */
    public static Bitmap getCompressBm(String filePath) {
        Bitmap bm = null;
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options);
        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, 500, 500);
        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        bm = BitmapFactory.decodeFile(filePath, options);
        return bm;
    }

    /**
     * 计算压缩比例
     *
     * @param options
     * @param reqWidth
     * @param reqHeight
     * @return
     */
    private static int calculateInSampleSize(BitmapFactory.Options options,
                                             int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {
            final int heightRatio = Math.round((float) height
                    / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);
            inSampleSize = heightRatio < widthRatio ? widthRatio : heightRatio;
        }

        return inSampleSize;
    }

    /**
     * 旋转图片
     *
     * @param bitmap
     * @param degress
     * @return
     */
    public static Bitmap rotateBitmap(Bitmap bitmap, int degress) {
        if (bitmap == null)
            return null;

        int w = bitmap.getWidth();
        int h = bitmap.getHeight();

        // Setting post rotate to 90
        Matrix mtx = new Matrix();
        mtx.postRotate(degress);
        return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
    }

    /**
     * 创建一个图片处理Options
     *
     * @return {@link android.graphics.BitmapFactory.Options}
     */
    public static BitmapFactory.Options createOptions() {
        return new BitmapFactory.Options();
    }

    /**
     * 把一个{@link android.graphics.BitmapFactory.Options}进行参数复原操作，
     * 避免重复创建新的 {@link android.graphics.BitmapFactory.Options}
     *
     * @param options {@link android.graphics.BitmapFactory.Options}
     */
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public static void resetOptions(BitmapFactory.Options options) {
        options.inTempStorage = null;
        options.inDither = false;
        options.inScaled = false;
        options.inSampleSize = 1;
        options.inPreferredConfig = null;
        options.inJustDecodeBounds = false;
        options.inDensity = 0;
        options.inTargetDensity = 0;
        options.outWidth = 0;
        options.outHeight = 0;
        options.outMimeType = null;

        if (Build.VERSION_CODES.HONEYCOMB <= Build.VERSION.SDK_INT) {
            options.inBitmap = null;
            options.inMutable = true;
        }
    }

    /**
     * 获取图片的真实后缀
     *
     * @param filePath 图片存储地址
     * @return 图片类型后缀
     */
    public static String getExtension(String filePath) {
        BitmapFactory.Options options = createOptions();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options);
        String mimeType = options.outMimeType;
        return mimeType.substring(mimeType.lastIndexOf("/") + 1);
    }

    public static Bitmap decodeBitmap(final File file,
                                      final int maxWidth,
                                      final int maxHeight,
                                      byte[] byteStorage,
                                      BitmapFactory.Options options,
                                      boolean exactDecode) {
        InputStream is;
        try {
            // In this, we can set the buffer size
            is = new BufferedInputStream(new FileInputStream(file),
                    byteStorage == null ? DEFAULT_BUFFER_SIZE : byteStorage.length);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return null;
        }

        if (options == null)
            options = createOptions();
        else
            resetOptions(options);

        // First decode with inJustDecodeBounds=true to check dimensions
        options.inJustDecodeBounds = true;

        // 5MB. This is the max image header size we can handle, we preallocate a much smaller buffer
        // but will resize up to this amount if necessary.
        is.mark(5 * 1024 * 1024);
        BitmapFactory.decodeStream(is, null, options);

        // Reset the inputStream
        try {
            is.reset();
        } catch (IOException e) {
            e.printStackTrace();
            IOUtil.close(is);
            resetOptions(options);
            return null;
        }

        // Calculate inSampleSize
        calculateScaling(options, maxWidth, maxHeight, exactDecode);

        // Init the BitmapFactory.Options.inTempStorage value
        if (byteStorage == null)
            byteStorage = new byte[DEFAULT_BUFFER_SIZE];
        options.inTempStorage = byteStorage;

        // Decode bitmap with inSampleSize set FALSE
        options.inJustDecodeBounds = false;
        Bitmap bitmap = BitmapFactory.decodeStream(is, null, options);

        // Close the Stream
        IOUtil.close(is);
        // And Reset the option
        resetOptions(options);

        // To scale bitmap to user set
        bitmap = scaleBitmap(bitmap, maxWidth, maxHeight, true);

        return bitmap;

    }

    /**
     * 按长宽比缩小一个Bitmap
     *
     * @param source        待缩小的{@link Bitmap}
     * @param scale         缩放比0～1，1代表不缩放
     * @param recycleSource 是否释放Bitmap源
     * @return 一个缩小后的Bitmap
     */
    public static Bitmap scaleBitmap(Bitmap source, float scale, boolean recycleSource) {
        if (scale <= 0 || scale >= 1)
            return source;
        Matrix m = new Matrix();
        final int width = source.getWidth();
        final int height = source.getHeight();
        m.setScale(scale, scale);
        Bitmap scaledBitmap = Bitmap.createBitmap(source, 0, 0, width, height, m, false);
        if (recycleSource)
            source.recycle();
        return scaledBitmap;
    }

    /**
     * 按照长宽比缩小一个Bitmap到指定尺寸，
     * 当传入的高宽都大于原始值时将不做缩小操作
     *
     * @param source          待缩小的{@link Bitmap}
     * @param targetMaxWidth  目标宽度
     * @param targetMaxHeight 目标高度
     * @param recycleSource   是否释放Bitmap源
     * @return 一个缩小后的Bitmap
     */
    public static Bitmap scaleBitmap(Bitmap source, int targetMaxWidth, int targetMaxHeight, boolean recycleSource) {
        int sourceWidth = source.getWidth();
        int sourceHeight = source.getHeight();

        Bitmap scaledBitmap = source;
        if (sourceWidth > targetMaxWidth || sourceHeight > targetMaxHeight) {
            float minScale = Math.min(targetMaxWidth / (float) sourceWidth,
                    targetMaxHeight / (float) sourceHeight);
            scaledBitmap = Bitmap.createScaledBitmap(scaledBitmap,
                    (int) (sourceWidth * minScale),
                    (int) (sourceHeight * minScale), false);
            if (recycleSource)
                source.recycle();
        }

        return scaledBitmap;
    }

    /**
     * 通过{@link android.graphics.BitmapFactory.Options}计算图片的缩放比,
     * 并将缩放后的信息存储在传入的{@link android.graphics.BitmapFactory.Options}中，
     * 以便后续的 {@link BitmapFactory#decodeStream(InputStream)}等操作
     *
     * @param options            一个图片的{@link android.graphics.BitmapFactory.Options}， 含有图片的基础信息
     * @param requestedMaxWidth  目标宽度
     * @param requestedMaxHeight 目标高度
     * @param exactDecode        是否精确计算，该参数只在 {@link android.os.Build.VERSION#SDK_INT} 大于 Api19 时有效
     */
    private static BitmapFactory.Options calculateScaling(BitmapFactory.Options options,
                                                          final int requestedMaxWidth,
                                                          final int requestedMaxHeight,
                                                          boolean exactDecode) {
        int sourceWidth = options.outWidth;
        int sourceHeight = options.outHeight;

        if (sourceWidth <= requestedMaxWidth && sourceHeight <= requestedMaxHeight) {
            return options;
        }

        final float maxFloatFactor = Math.max(sourceHeight / (float) requestedMaxHeight,
                sourceWidth / (float) requestedMaxWidth);
        final int maxIntegerFactor = (int) Math.floor(maxFloatFactor);
        final int lesserOrEqualSampleSize = Math.max(1, Integer.highestOneBit(maxIntegerFactor));

        options.inSampleSize = lesserOrEqualSampleSize;
        // Density scaling is only supported if inBitmap is null prior to KitKat. Avoid setting
        // densities here so we calculate the final Bitmap size correctly.
        if (exactDecode && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            float scaleSize = sourceWidth / (float) lesserOrEqualSampleSize;
            float outSize = sourceWidth / maxFloatFactor;

            options.inTargetDensity = 1000;
            options.inDensity = (int) (1000 * (scaleSize / outSize) + 0.5);

            // If isScaling
            if (options.inTargetDensity != options.inDensity) {
                options.inScaled = true;
            } else {
                options.inDensity = options.inTargetDensity = 0;
            }
        }
        return options;
    }

    public final static class Compressor {

        public static File compressImage(final File sourceFile, final long maxSize,
                                         final int minQuality, final int maxWidth,
                                         final int maxHeight) {
            return compressImage(sourceFile, maxSize, minQuality, maxWidth, maxHeight, true);
        }

        public static File compressImage(final File sourceFile, final long maxSize,
                                         final int minQuality, final int maxWidth,
                                         final int maxHeight, boolean exactDecode) {
            return compressImage(sourceFile, maxSize, minQuality, maxWidth, maxHeight, null, null, exactDecode);
        }

        /**
         * 压缩图片
         *
         * @param sourceFile  原图地址
         * @param maxSize     最大文件地址byte
         * @param minQuality  最小质量
         * @param maxWidth    最大宽度
         * @param maxHeight   最大高度
         * @param byteStorage 用于批量压缩时的buffer，不必要为null，
         *                    需要时，推荐 {{@link #DEFAULT_BUFFER_SIZE}}
         * @param options     批量压缩时复用参数，可调用 {{@link #createOptions()}} 得到
         * @param exactDecode 是否精确解码， TRUE： 在4.4及其以上机器中能更节约内存
         * @return 返回压缩后的图片文件，该图片存储在原图同级目录下，以compress.temp结尾
         */
        public static File compressImage(final File sourceFile,
                                         final long maxSize,
                                         final int minQuality,
                                         final int maxWidth,
                                         final int maxHeight,
                                         byte[] byteStorage,
                                         BitmapFactory.Options options,
                                         boolean exactDecode) {
            // build source file
            if (sourceFile == null || !sourceFile.exists() || !sourceFile.canRead())
                return null;

            // create new temp file
            final File tempFile = new File(sourceFile.getParent(),
                    String.format("compress_%s.temp", System.currentTimeMillis()));

            if (!tempFile.exists()) {
                try {
                    if (!tempFile.createNewFile())
                        return null;
                } catch (IOException e) {
                    e.printStackTrace();
                    return null;
                }
            }

            // build to bitmap
            Bitmap bitmap = decodeBitmap(sourceFile, maxWidth, maxHeight, byteStorage, options, exactDecode);
            if (bitmap == null)
                return null;

            // Get the bitmap format
            Bitmap.CompressFormat compressFormat = bitmap.hasAlpha() ?
                    Bitmap.CompressFormat.PNG : Bitmap.CompressFormat.JPEG;

            // Write to out put file
            boolean isOk = false;
            for (int i = 1; i <= 10; i++) {
                // In this we change the quality start 92%
                int quality = 92;
                for (; ; ) {
                    BufferedOutputStream outputStream = null;
                    try {
                        outputStream = new BufferedOutputStream(new FileOutputStream(tempFile));
                        bitmap.compress(compressFormat, quality, outputStream);
                    } catch (IOException e) {
                        e.printStackTrace();
                        // on IOException we need recycle the bitmap
                        bitmap.recycle();
                        return null;
                    } finally {
                        IOUtil.close(outputStream);
                    }
                    // Check file size
                    long outSize = tempFile.length();
                    if (outSize <= maxSize) {
                        isOk = true;
                        break;
                    }
                    if (quality < minQuality)
                        break;
                    quality--;
                }

                if (isOk) {
                    break;
                } else {
                    // If not ok, we need scale the Bitmap to small
                    // In this, once subtract 2%, most 20%
                    bitmap = scaleBitmap(bitmap, 1 - (0.2f * i), true);
                }
            }
            // recycle bitmap
            bitmap.recycle();

            // The end, If not success, return false
            if (!isOk)
                return null;

            // Rename to out file
            return tempFile;
        }
    }

    /**
     * 获得带倒影的图片方法
     *
     * @param bitmap
     * @return
     */
    public static Bitmap createReflectionImageWithOrigin(Bitmap bitmap) {
        final int reflectionGap = 4;
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();

        Matrix matrix = new Matrix();
        matrix.preScale(1, -1);

        Bitmap reflectionImage = Bitmap.createBitmap(bitmap, 0, height / 2,
                width, height / 2, matrix, false);

        Bitmap bitmapWithReflection = Bitmap.createBitmap(width,
                (height + height / 2), Config.ARGB_8888);

        Canvas canvas = new Canvas(bitmapWithReflection);
        canvas.drawBitmap(bitmap, 0, 0, null);
        Paint deafalutPaint = new Paint();
        canvas.drawRect(0, height, width, height + reflectionGap, deafalutPaint);

        canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);

        Paint paint = new Paint();
        LinearGradient shader = new LinearGradient(0, bitmap.getHeight(), 0,
                bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff,
                0x00ffffff, Shader.TileMode.CLAMP);
        paint.setShader(shader);
        // Set the Transfer mode to be porter duff and destination in
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        // Draw a rectangle using the paint with our linear gradient
        canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()
                + reflectionGap, paint);

        return bitmapWithReflection;
    }

    /**
     * 获得圆角图片的方法
     *
     * @param bitmap
     * @param roundPx 一般设成14
     * @return
     */
    public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) {

        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
                bitmap.getHeight(), Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        final RectF rectF = new RectF(rect);

        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);

        return output;
    }

    /**
     * 将Drawable转化为Bitmap
     *
     * @param drawable
     * @return
     */
    public static Bitmap drawableToBitmap(Drawable drawable) {
        int width = drawable.getIntrinsicWidth();
        int height = drawable.getIntrinsicHeight();
        Bitmap bitmap = Bitmap.createBitmap(width, height, drawable
                .getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
                : Bitmap.Config.RGB_565);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, width, height);
        drawable.draw(canvas);
        return bitmap;

    }

    public static Bitmap scaleBitmap(Bitmap bitmap) {
        // 获取这个图片的宽和高
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        // 定义预转换成的图片的宽度和高度
        int newWidth = 200;
        int newHeight = 200;
        // 计算缩放率，新尺寸除原始尺寸
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        // 创建操作图片用的matrix对象
        Matrix matrix = new Matrix();
        // 缩放图片动作
        matrix.postScale(scaleWidth, scaleHeight);
        // 旋转图片 动作
        // matrix.postRotate(45);
        // 创建新的图片
        Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height,
                matrix, true);
        return resizedBitmap;
    }

    /**
     * 放大缩小图片
     *
     * @param bitmap
     * @param w
     * @param h
     * @return
     */
    public static Bitmap zoomBitmap(Bitmap bitmap, int w, int h) {
        Bitmap newbmp = null;
        if (bitmap != null) {
            int width = bitmap.getWidth();
            int height = bitmap.getHeight();
            Matrix matrix = new Matrix();
            float scaleWidht = ((float) w / width);
            float scaleHeight = ((float) h / height);
            matrix.postScale(scaleWidht, scaleHeight);
            newbmp = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix,
                    true);
        }
        return newbmp;
    }

    /**
     * 创建缩略图
     *
     * @param context
     * @param largeImagePath 原始大图路径
     * @param thumbfilePath  输出缩略图路径
     * @param square_size    输出图片宽度
     * @param quality        输出图片质量
     * @throws IOException
     */
    public static void createImageThumbnail(Context context,
                                            String largeImagePath, String thumbfilePath, int square_size,
                                            int quality) throws IOException {
        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inSampleSize = 1;
        // 原始图片bitmap
        Bitmap cur_bitmap = getBitmapByPath(largeImagePath, opts);

        if (cur_bitmap == null)
            return;

        // 原始图片的高宽
        int[] cur_img_size = new int[]{cur_bitmap.getWidth(),
                cur_bitmap.getHeight()};
        // 计算原始图片缩放后的宽高
        int[] new_img_size = scaleImageSize(cur_img_size, square_size);
        // 生成缩放后的bitmap
        Bitmap thb_bitmap = zoomBitmap(cur_bitmap, new_img_size[0],
                new_img_size[1]);
        // 生成缩放后的图片文件
        saveImageToSD(null, thumbfilePath, thb_bitmap, quality);
    }

    /**
     * 计算缩放图片的宽高
     *
     * @param img_size
     * @param square_size
     * @return
     */
    public static int[] scaleImageSize(int[] img_size, int square_size) {
        if (img_size[0] <= square_size && img_size[1] <= square_size)
            return img_size;
        double ratio = square_size
                / (double) Math.max(img_size[0], img_size[1]);
        return new int[]{(int) (img_size[0] * ratio),
                (int) (img_size[1] * ratio)};
    }

    /**
     * 获取图片缩略图 只有Android2.1以上版本支持
     *
     * @param imgName
     * @param kind    MediaStore.Images.Thumbnails.MICRO_KIND
     * @return
     */
    @SuppressWarnings("deprecation")
    public static Bitmap loadImgThumbnail(Activity context, String imgName,
                                          int kind) {
        Bitmap bitmap = null;

        String[] proj = {MediaStore.Images.Media._ID,
                MediaStore.Images.Media.DISPLAY_NAME};

        Cursor cursor = context.managedQuery(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI, proj,
                MediaStore.Images.Media.DISPLAY_NAME + "='" + imgName + "'",
                null, null);

        if (cursor != null && cursor.getCount() > 0 && cursor.moveToFirst()) {
            ContentResolver crThumb = context.getContentResolver();
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inSampleSize = 1;
            bitmap = getThumbnail(crThumb, cursor.getInt(0),
                    kind, options);
        }
        return bitmap;
    }

    public static Bitmap loadImgThumbnail(String filePath, int w, int h) {
        Bitmap bitmap = getBitmapByPath(filePath);
        return zoomBitmap(bitmap, w, h);
    }

    @TargetApi(7)
    public static Bitmap getThumbnail(ContentResolver cr, long origId, int kind, BitmapFactory.Options options) {
        return MediaStore.Images.Thumbnails.getThumbnail(cr, origId, kind, options);
    }

    /**
     * 通过uri获取文件的绝对路径
     *
     * @param uri
     * @return
     */
    @SuppressWarnings("deprecation")
    public static String getAbsoluteImagePath(Activity context, Uri uri) {
        String imagePath = "";
        String[] proj = {MediaStore.Images.Media.DATA};
        Cursor cursor = context.managedQuery(uri, proj, // Which columns to
                // return
                null, // WHERE clause; which rows to return (all rows)
                null, // WHERE clause selection arguments (none)
                null); // Order-by clause (ascending by name)

        if (cursor != null) {
            int column_index = cursor
                    .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            if (cursor.getCount() > 0 && cursor.moveToFirst()) {
                imagePath = cursor.getString(column_index);
            }
        }

        return imagePath;
    }

    /**
     * 获取bitmap
     *
     * @param file
     * @return
     */
    public static Bitmap getBitmapByFile(File file) {
        FileInputStream fis = null;
        Bitmap bitmap = null;
        try {
            fis = new FileInputStream(file);
            bitmap = BitmapFactory.decodeStream(fis);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (OutOfMemoryError e) {
            e.printStackTrace();
        } finally {
            try {
                fis.close();
            } catch (Exception e) {
            }
        }
        return bitmap;
    }

    /**
     * 获取bitmap
     *
     * @param filePath
     * @return
     */
    public static Bitmap getBitmapByPath(String filePath) {
        return getBitmapByPath(filePath, null);
    }


    public static Bitmap getBitmapByPath(String filePath,
                                         BitmapFactory.Options opts) {
        FileInputStream fis = null;
        Bitmap bitmap = null;
        try {
            File file = new File(filePath);
            fis = new FileInputStream(file);
            bitmap = BitmapFactory.decodeStream(fis, null, opts);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (OutOfMemoryError e) {
            e.printStackTrace();
        } finally {
            try {
                fis.close();
            } catch (Exception e) {
            }
        }
        return bitmap;
    }

    /**
     * 获取bitmap
     *
     * @param context
     * @param fileName
     * @return
     */
    public static Bitmap getBitmap(Context context, String fileName) {
        FileInputStream fis = null;
        Bitmap bitmap = null;
        try {
            fis = context.openFileInput(fileName);
            bitmap = BitmapFactory.decodeStream(fis);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (OutOfMemoryError e) {
            e.printStackTrace();
        } finally {
            try {
                fis.close();
            } catch (Exception e) {
            }
        }
        return bitmap;
    }

    /**
     * 写图片文件到SD卡
     *
     * @throws IOException
     */
    public static void saveImageToSD(Context ctx, String filePath,
                                     Bitmap bitmap, int quality) throws IOException {
        if (bitmap != null) {
            File file = new File(filePath.substring(0,
                    filePath.lastIndexOf(File.separator)));
            if (!file.exists()) {
                file.mkdirs();
            }
            BufferedOutputStream bos = new BufferedOutputStream(
                    new FileOutputStream(filePath));
            bitmap.compress(Bitmap.CompressFormat.PNG, quality, bos);
            bos.flush();
            bos.close();
            if (ctx != null) {
                scanPhoto(ctx, filePath);
            }
        }
    }

    public static void saveImage(Context context, String fileName,
                                 Bitmap bitmap, int quality) throws IOException {
        if (bitmap == null || fileName == null || context == null)
            return;

        FileOutputStream fos = context.openFileOutput(fileName,
                Context.MODE_PRIVATE);
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, stream);
        byte[] bytes = stream.toByteArray();
        fos.write(bytes);
        fos.close();
    }

    /**
     * 让能马上看到该图片
     */
    private static void scanPhoto(Context ctx, String imgFileName) {
        Intent mediaScanIntent = new Intent(
                Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        File file = new File(imgFileName);
        Uri contentUri = Uri.fromFile(file);
        mediaScanIntent.setData(contentUri);
        ctx.sendBroadcast(mediaScanIntent);
    }


    /**
     * 写图片文件 在Android系统中，文件保存在 /data/data/PACKAGE_NAME/files 目录下
     *
     * @throws IOException
     */
    public static void saveImage(Context context, String fileName, Bitmap bitmap)
            throws IOException {
        saveImage(context, fileName, bitmap, 100);
    }

    /**
     * @param path
     * @param strFilePath
     * @param bitmap
     * @return
     */
    public static File saveBitmap(String path, String strFilePath, Bitmap bitmap) {
        File file = new File(path);
        File newFile = new File(strFilePath, file.getName());
        try {
            FileOutputStream out = new FileOutputStream(newFile);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
            out.flush();
            out.close();
            return newFile;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

}
